home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / sbin / deluser < prev    next >
Encoding:
Text File  |  2010-11-21  |  15.4 KB  |  520 lines

  1. #!/usr/bin/perl
  2.  
  3. # deluser -- a utility to remove users from the system
  4. # delgroup -- a utilty to remove groups from the system
  5. my $version = "3.112+nmu2";
  6.  
  7. # Copyright (C) 2000 Roland Bauerschmidt <rb@debian.org>
  8. # Based on 'adduser' as pattern by
  9. #     Guy Maor <maor@debian.org>
  10. #     Ted Hajek <tedhajek@boombox.micro.umn.edu>
  11. #     Ian A. Murdock <imurdock@gnu.ai.mit.edu>
  12.  
  13. # This program is free software; you can redistribute it and/or modify
  14. # it under the terms of the GNU General Public License as published by
  15. # the Free Software Foundation; either version 2 of the License, or
  16. # (at your option) any later version.
  17. #
  18. # This program is distributed in the hope that it will be useful,
  19. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. # GNU General Public License for more details.
  22. #
  23. # You should have received a copy of the GNU General Public License
  24. # along with this program; if not, write to the Free Software
  25. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  26.  
  27. ####################
  28. # See the usage subroutine for explanation about how the program can be called
  29. ####################
  30.  
  31. use warnings;
  32. use strict;
  33. use Getopt::Long;
  34. use Debian::AdduserCommon;
  35.  
  36. my $install_more_packages ;
  37.  
  38. BEGIN {
  39.     local $ENV{PERL_DL_NONLAZY}=1;
  40.     eval 'use File::Find';
  41.     if ($@) {
  42.       $install_more_packages = 1;
  43.     }
  44.     #no warnings "File::Find";
  45.     eval 'use File::Temp';
  46.     if ($@) {
  47.       $install_more_packages = 1;
  48.     }
  49. }
  50.  
  51.  
  52. BEGIN {
  53.     eval 'use Locale::gettext';
  54.     if ($@) {
  55.         *gettext = sub { shift };
  56.         *textdomain = sub { "" };
  57.         *LC_MESSAGES = sub { 5 };
  58.     }
  59.     eval {
  60.         require POSIX;
  61.         import POSIX qw(setlocale);
  62.     };
  63.     if ($@) {
  64.         *setlocale = sub { return 1 };
  65.     }
  66. }
  67.  
  68. setlocale(LC_MESSAGES, "");
  69. textdomain("adduser");
  70.  
  71. my $action = $0 =~ /delgroup$/ ? "delgroup" : "deluser";
  72. our $verbose = 1;
  73. my %pconfig = ();
  74. my %config = ();
  75. my $configfile;
  76. my @defaults;
  77. my $force;
  78.  
  79.  
  80. unless ( GetOptions ("quiet|q" => sub {$verbose = 0; },
  81.             "debug" => sub {$verbose = 2; },
  82.         "version|v" => sub { &version(); exit 0; },
  83.         "help|h" => sub { &usage(); exit 0;},
  84.         "group" => sub { $action = "delgroup";},
  85.         "conf=s" => \$configfile,
  86.         "system" => \$pconfig{"system"},
  87.         "only-if-empty" => \$pconfig{"only_if_empty"},
  88.         "remove-home" => \$pconfig{"remove_home"},
  89.         "remove-all-files" => \$pconfig{"remove_all_files"},
  90.         "backup" => \$pconfig{"backup"},
  91.         "backup-to=s" => \$pconfig{"backup_to"},
  92.             "force" => \$force
  93.        ) ) {
  94.     &usage;
  95.     exit 1;
  96. }
  97.  
  98. # everyone can issue "--help" and "--version", but only root can go on
  99. dief (gtx("Only root may remove a user or group from the system.\n")) if ($> != 0);
  100.  
  101. if (!defined($configfile)) { 
  102.     @defaults = ("/etc/adduser.conf", "/etc/deluser.conf");
  103. } else {
  104.     @defaults = ($configfile);
  105. }
  106.  
  107. # explicitly set PATH, because super (1) cleans up the path and makes deluser unusable;
  108. # this is also a good idea for sudo (which doesn't clean up)
  109. $ENV{"PATH"}="/bin:/usr/bin:/sbin:/usr/sbin";
  110.  
  111. my @names = ();
  112. my ($user,$group);
  113.  
  114. ######################
  115. # handling of @names #
  116. ######################
  117.  
  118. while (defined(my $arg = shift(@ARGV))) {
  119.   if (defined($names[0]) && $arg =~ /^--/) {
  120.       dief (gtx("No options allowed after names.\n"));
  121.     } else {            # it's a username
  122.     push (@names, $arg);
  123.     }
  124. }
  125.  
  126. if(@names == 0) {
  127.     if($action eq "delgroup") {
  128.     print (gtx("Enter a group name to remove: "));
  129.     } else {
  130.     print (gtx("Enter a user name to remove: "));
  131.     }
  132.     chomp(my $answer=<STDIN>);
  133.     push(@names, $answer);
  134. }
  135.  
  136. if (length($names[0]) == 0 || @names > 2) {
  137.     dief (gtx("Only one or two names allowed.\n"));
  138. }
  139.  
  140. if(@names == 2) {      # must be deluserfromgroup
  141.     $action = "deluserfromgroup";
  142.     $user = shift(@names);
  143.     $group = shift(@names);
  144. } else {
  145.     if($action eq "delgroup") {
  146.     $group = shift(@names);
  147.     } else {
  148.     $user = shift(@names);
  149.     }
  150. }
  151.  
  152. undef(@names);
  153.  
  154.  
  155. ##########################################################
  156. # (1) preseed the config
  157. # (2) read the default /etc/adduser.conf configuration.
  158. # (3) read the default /etc/deluser.conf configuration.
  159. # (4) process commmand line settings
  160. # last match wins
  161. ##########################################################
  162.  
  163. preseed_config (\@defaults,\%config);
  164.  
  165. foreach(keys(%pconfig)) {
  166.     $config{$_} = $pconfig{$_} if ($pconfig{$_});
  167. }
  168.  
  169. if (($config{remove_home} || $config{remove_all_files} || $config{backup}) && ($install_more_packages)) {
  170.     fail (8, gtx("In order to use the --remove-home, --remove-all-files, and --backup features,
  171. you need to install the `perl-modules' package. To accomplish that, run
  172. apt-get install perl-modules.\n"));
  173. }
  174.  
  175.  
  176. my ($pw_uid, $pw_gid, $pw_homedir, $gr_gid, $maingroup);
  177.  
  178. if($user) {
  179.     my @passwd = getpwnam($user);
  180.     $pw_uid = $passwd[2];
  181.     $pw_gid = $passwd[3];
  182.     $pw_homedir = $passwd[7];
  183.     
  184.     $maingroup = $pw_gid ? getgrgid($pw_gid) : "";
  185. }
  186. if($group) {
  187.     #($gr_name,$gr_passwd,$gr_gid,$gr_members) = getgrnam($group);
  188.     my @group = getgrnam($group);
  189.     $gr_gid = $group[2];
  190. }
  191.  
  192. # arguments are processed:
  193. #
  194. #  $action = "deluser"
  195. #     $user          name of the user to remove
  196. #
  197. #  $action = "delgroup"
  198. #     $group         name of the group to remove
  199. #
  200. #  $action = "deluserfromgroup"
  201. #     $user          the user to be remove
  202. #     $group         the group to remove him/her from
  203.  
  204.  
  205. if($action eq "deluser") {
  206.     &invalidate_nscd();
  207.     
  208.     my($dummy1,$dummy2,$uid);
  209.  
  210.  
  211.  
  212.     # Don't allow a non-system user to be deleted when --system is given
  213.     # Also, "user does not exist" is only a warning with --system, but an
  214.     # error without --system.
  215.     if( $config{"system"} ) {
  216.     if( ($dummy1,$dummy2,$uid) = getpwnam($user) ) {
  217.         if ( ($uid < $config{"first_system_uid"} ||
  218.         $uid > $config{"last_system_uid" } ) ) {
  219.         printf (gtx("The user `%s' is not a system user. Exiting.\n"), $user) if $verbose;
  220.         exit 1;
  221.         }
  222.         } else {
  223.         printf (gtx("The user `%s' does not exist, but --system was given. Exiting.\n"), $user) if $verbose;
  224.         exit 0;
  225.     }
  226.     }
  227.     
  228.     unless(exist_user($user)) {
  229.     fail (2,gtx("The user `%s' does not exist.\n"),$user);
  230.     }
  231.     
  232.     # Warn in any case if you want to remove the root account 
  233.     if ((defined($pw_uid)) && ($pw_uid == 0) && (!defined($force)))  {
  234.         printf (gtx("WARNING: You are just about to delete the root account (uid 0)\n"));
  235.         printf (gtx("Usually this is never required as it may render the whole system unusable\n"));
  236.         printf (gtx("If you really want this, call deluser with parameter --force\n"));
  237.         printf (gtx("Stopping now without having performed any action\n"));
  238.         exit 9;
  239.     }
  240.  
  241.     # consistency check
  242.     # if --backup-to is specified, --backup should be set too
  243.     if ($pconfig{"backup_to"}) {
  244.         $config{"backup"} = 1;
  245.     }
  246.  
  247.     if($config{"remove_home"} || $config{"remove_all_files"}) {
  248.       s_print (gtx("Looking for files to backup/remove ...\n"));
  249.       my @mountpoints;
  250.       open(MOUNT, "mount |")
  251.           || fail (4 ,gtx("fork for `mount' to parse mount points failed: %s\n", $!));
  252.       while (<MOUNT>) {
  253.           my @temparray = split;
  254.           my $fstype = $temparray[4];
  255.           my $exclude_fstypes = $config{"exclude_fstypes"};
  256.           if (defined($exclude_fstypes)) {
  257.               next if ($fstype =~ /$exclude_fstypes/);
  258.           }
  259.           push @mountpoints,$temparray[2];
  260.       }
  261.       close(MOUNT) or dief (gtx("pipe of command `mount' could not be closed: %s\n",$!));
  262.       my(@files,@dirs);
  263.       if($config{"remove_home"} && ! $config{"remove_all_files"}) {
  264.  
  265.         # collect all files in user home
  266.     sub home_match {
  267.       # according to the manpage
  268.       foreach my $mount (@mountpoints) {
  269.         if( $File::Find::name eq $mount ) {
  270.           s_printf (gtx("Not backing up/removing `%s', it is a mount point.\n"),$File::Find::name);
  271.           $File::Find::prune=1;
  272.           return;
  273.         }
  274.       }
  275.       foreach my $re ( split ' ', $config{"no_del_paths"} ) {
  276.         if( $File::Find::name =~ qr/$re/ ) {
  277.           s_printf (gtx("Not backing up/removing `%s', it matches %s.\n"),$File::Find::name,$re);
  278.           $File::Find::prune=1;
  279.           return;
  280.         }
  281.       }
  282.  
  283.       push(@files, $File::Find::name) 
  284.         if(-f $File::Find::name || -l $File::Find::name);
  285.       push(@dirs, $File::Find::name)
  286.         if(-d $File::Find::name);
  287.     } # sub home_match
  288.     
  289.     File::Find::find({wanted => \&home_match, untaint => 1, no_chdir => 1}, $pw_homedir)
  290.       if(-d "$pw_homedir");
  291.     push(@files, "/var/mail/$user")
  292.       if(-e "/var/mail/$user");
  293.       } else {
  294.  
  295.         # collect all files on system belonging to that user
  296.     sub find_match {
  297.       my ($dev,$ino,$mode,$nlink,$uid,$gid);
  298.       (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
  299.         ($uid == $pw_uid) &&
  300.           (
  301.         ($File::Find::name =~ /^\/proc\// && ($File::Find::prune = 1)) ||
  302.         (-f $File::Find::name && push(@files, $File::Find::name)) ||
  303.         (-d $File::Find::name && push(@dirs, $File::Find::name)) ||
  304.                 (-l $File::Find::name && push(@dirs, $File::Find::name)) ||
  305.                 (-S $File::Find::name && push(@dirs, $File::Find::name)) || 
  306.                 (-p $File::Find::name && push(@dirs, $File::Find::name))
  307.           );
  308.               if ( -b $File::Find::name || -c $File::Find::name ) {
  309.                warnf (gtx("Cannot handle special file %s\n"),$File::Find::name);
  310.               }
  311.     } # sub find_match
  312.     
  313.     File::Find::find({wanted => \&find_match, untaint => 1, no_chdir => 1}, '/');
  314.       }
  315.  
  316.       if($config{"backup"}) {
  317.      s_printf (gtx("Backing up files to be removed to %s ...\n"),$config{"backup_to"});
  318.      my $filesfile = new File::Temp(TEMPLATE=>"deluser.XXXXX", DIR=>"/tmp");
  319.      my $filesfilename = $filesfile->filename;
  320.      my $backup_name = $config{"backup_to"} . "/$user.tar";
  321.      print "backup_name = $backup_name";
  322.      print $filesfile join("\n",@files);
  323.      $filesfile->close();
  324.          my $tar = &which('tar');
  325.          my $bzip2 = &which('bzip2', 1);
  326.          my $gzip = &which('gzip', 1);
  327.          my $options = '';
  328.      if($bzip2) {
  329.              $backup_name = "$backup_name.bz2";
  330.              $options = "--bzip2";
  331.      } elsif($gzip) {
  332.              $backup_name = "$backup_name.gz";
  333.              $options = "--gzip";
  334.      }
  335.      &systemcall($tar, $options, "-cf", $backup_name, "--files-from", $filesfilename);
  336.      chmod 0600, $backup_name;
  337.          my $rootid = 0;
  338.      chown $rootid, $rootid, $backup_name;
  339.      unlink($filesfilename);
  340.       }
  341.  
  342.       if(@files || @dirs) {
  343.       s_print (gtx("Removing files ...\n"));
  344.       unlink(@files) if(@files);
  345.       foreach(reverse(sort(@dirs))) {
  346.           rmdir($_);
  347.       }
  348.       }
  349.     }
  350.  
  351.     if (system("crontab -l $user >/dev/null 2>&1") == 0) {
  352.       # crontab -l returns 1 if there is no crontab
  353.       my $crontab = &which('crontab');
  354.       &systemcall($crontab, "-r", $user);
  355.       s_print (gtx("Removing crontab ...\n"));
  356.     }
  357.  
  358.     s_printf (gtx("Removing user `%s' ...\n"),$user);
  359.     my @members = get_group_members($maingroup);
  360.     if (@members == 0) {
  361.         s_printf (gtx("Warning: group `%s' has no more members.\n"), $maingroup);    
  362.     }
  363.     my $userdel = &which('userdel');
  364.     &systemcall($userdel, $user);
  365.     &invalidate_nscd();
  366.  
  367.     systemcall('/usr/local/sbin/deluser.local', $user, $pw_uid,
  368.                 $pw_gid, $pw_homedir) if (-x "/usr/local/sbin/deluser.local");
  369.  
  370.     s_print (gtx("Done.\n"));
  371.     exit 0;
  372. }
  373.  
  374.     
  375. if($action eq "delgroup") {
  376.     &invalidate_nscd();
  377.     unless(exist_group($group)) {
  378.     printf( gtx("The group `%s' does not exist.\n"),$group) if $verbose;
  379.         exit 3;
  380.     }
  381.     my($dummy,$gid,$members);
  382.     if( !(($dummy, $dummy, $gid, $members ) = getgrnam($group)) ) {
  383.     fail (4 ,gtx("getgrnam `%s' failed. This shouldn't happen.\n"), $group);
  384.     }
  385.     if( $config{"system"} && 
  386.     ($gid < $config{"first_system_gid"} ||
  387.      $gid > $config{"last_system_gid" } )) {
  388.         printf (gtx("The group `%s' is not a system group. Exiting.\n"), $group) if $verbose;
  389.     exit 3;
  390.     }
  391.     if( $config{"only_if_empty"} && $members ne "") {
  392.     fail (5, gtx("The group `%s' is not empty!\n"),$group);
  393.     }
  394.     
  395.     setpwent;
  396.     while ((my $acctname,my $primgrp) = (getpwent)[0,3]) {
  397.     if( $primgrp eq $gr_gid ) {
  398.         fail (7, gtx("`%s' still has `%s' as their primary group!\n"),$acctname,$group);
  399.     }
  400.     }
  401.     endpwent;
  402.  
  403.     s_printf (gtx("Removing group `%s' ...\n"),$group);
  404.     my $groupdel = &which('groupdel');
  405.     &systemcall($groupdel,$group);
  406.     &invalidate_nscd();
  407.     s_print (gtx("Done.\n"));
  408.     exit 0;
  409. }
  410.  
  411.  
  412. if($action eq "deluserfromgroup")
  413. {
  414.     &invalidate_nscd();
  415.     unless(exist_user($user)) {
  416.     fail (2, gtx("The user `%s' does not exist.\n"),$user);
  417.     }
  418.     unless(exist_group($group)) {
  419.     fail (3, gtx("The group `%s' does not exist.\n"),$group);
  420.     }
  421.     if($maingroup eq $group) {
  422.     fail (7, gtx("You may not remove the user from their primary group.\n"));
  423.     }
  424.  
  425.     my @members = get_group_members($group);
  426.     my $ismember = 0;
  427.  
  428.     for(my $i = 0; $i <= $#members; $i++) {
  429.     if($members[$i] eq $user) {
  430.         $ismember = 1;
  431.         splice(@members,$i,1);
  432.     }
  433.     }
  434.  
  435.     unless($ismember) {
  436.     fail (6, gtx("The user `%s' is not a member of group `%s'.\n"),$user,$group);
  437.     }
  438.  
  439.     s_printf (gtx("Removing user `%s' from group `%s' ...\n"),$user,$group);
  440.     #systemcall("usermod","-G", join(",",@groups), $user );
  441.     my $gpasswd = &which('gpasswd');
  442.     &systemcall($gpasswd,'-M', join(',',@members), $group);
  443.     &invalidate_nscd();
  444.     s_print (gtx("Done.\n"));
  445. }
  446.  
  447.  
  448. ######
  449.  
  450. sub fail {
  451.   my ($errorcode, $format, @args) = @_;
  452.   printf STDERR "$0: $format",@args;
  453.   exit $errorcode;
  454.  
  455. }
  456.  
  457. sub version {
  458.     printf (gtx("deluser version %s\n\n"), $version);
  459.     printf (gtx("Removes users and groups from the system.\n"));
  460.     
  461.     printf gtx("Copyright (C) 2000 Roland Bauerschmidt <roland\@copyleft.de>\n\n");
  462.  
  463.     printf gtx("deluser is based on adduser by Guy Maor <maor\@debian.org>, Ian Murdock\n".
  464.       "<imurdock\@gnu.ai.mit.edu> and Ted Hajek <tedhajek\@boombox.micro.umn.edu>\n\n");
  465.  
  466.     printf gtx("This program is free software; you can redistribute it and/or modify
  467. it under the terms of the GNU General Public License as published by
  468. the Free Software Foundation; either version 2 of the License, or (at
  469. your option) any later version.
  470.  
  471. This program is distributed in the hope that it will be useful, but
  472. WITHOUT ANY WARRANTY; without even the implied warranty of
  473. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  474. General Public License, /usr/share/common-licenses/GPL, for more details.\n");
  475. }
  476.  
  477. sub usage {
  478.     printf gtx(
  479. "deluser USER
  480.   remove a normal user from the system
  481.   example: deluser mike
  482.  
  483.   --remove-home             remove the users home directory and mail spool
  484.   --remove-all-files        remove all files owned by user
  485.   --backup                  backup files before removing.
  486.   --backup-to <DIR>         target directory for the backups.
  487.                             Default is the current directory.
  488.   --system                  only remove if system user
  489.  
  490. delgroup GROUP
  491. deluser --group GROUP
  492.   remove a group from the system
  493.   example: deluser --group students
  494.  
  495.   --system                  only remove if system group
  496.   --only-if-empty           only remove if no members left
  497.  
  498. deluser USER GROUP
  499.   remove the user from a group
  500.   example: deluser mike students
  501.  
  502. general options:
  503.   --quiet | -q      don't give process information to stdout
  504.   --help | -h       usage message
  505.   --version | -v    version number and copyright
  506.   --conf | -c FILE  use FILE as configuration file\n\n");
  507. }
  508.  
  509. sub exist_user {
  510.     my $exist_user = shift;
  511.     return(defined getpwnam($exist_user));
  512. }
  513.  
  514. sub exist_group {
  515.     my $exist_group = shift;
  516.     return(defined getgrnam($exist_group));
  517. }
  518.  
  519. # vim:set ai et sts=4 sw=4 tw=0:
  520.